/*
                    Chatbox Class Implementation
*/
#include "Chatbox.h"

Chatbox::Chatbox()
{
    iMaxLines = 50;
    iTextSize = 11;
    iCurrentLine = -1;
    iWidth = 0;
    iHeight = 0;

    Position = Point(0, 0);

    MessageFont = NULL;

    bVisible = true;

    iTotalHeight = 0;

    bAutoscroll = false;
}

Chatbox::~Chatbox()
{
    TTF_CloseFont(MessageFont);
    MessageFont = NULL;

    for (int i = 0; i < Lines.size(); i++)
    {
        SDL_FreeSurface(Lines.at(i));
    }
    Lines.clear();
}

int Chatbox::Initialise(Point NewPosition, string strFontFilepath, int iNewSize,
                           int iNewWidth, int iNewHeight, int iNewMaxLines)
{
    Position = NewPosition;

    iTotalHeight = 0;

    iTextSize = iNewSize;

    iWidth = iNewWidth;
    iHeight = iNewHeight;

    iMaxLines = iNewMaxLines;

    Scrollbar.Initialise(Point(0, 0),
                        "data//interface//ingame//fscrolltop.png",
                        "data//interface//ingame//fscrollbottom.png",
                        "data//interface//ingame//fscrollback.png",
                        "data//interface//ingame//fscroll.png",
                        iHeight, 0
                        );

    Scrollbar.setScrollEnabled(false);

    Scrollbar.setPosition(Point(Position.x + iWidth, Position.y));

    MessageFont = TTF_OpenFont(strFontFilepath.c_str(), iTextSize);
}

int Chatbox::HandleMouseDown(int iMouseX, int iMouseY)
{
    return Scrollbar.HandleMouseDown(iMouseX, iMouseY);
}

int Chatbox::HandleMouseMotion(int iMouseXREL, int iMouseYREL)
{
    return Scrollbar.HandleMouseMotion(iMouseXREL, iMouseYREL);
}

int Chatbox::HandleMouseUp(int iMouseX, int iMouseY)
{
    return Scrollbar.HandleMouseUp(iMouseX, iMouseY);
}

int Chatbox::AddMessage(string strPlayer, UnicodeString ustrMessage, SDL_Color MessageColour)
{
    UnicodeString ustrBuffer(strPlayer);
    ustrBuffer += ustrMessage;

    if (ustrBuffer.size() <= 0)
    {
        return -1;
    }

    int w = 0;

    TTF_SizeUNICODE(MessageFont, ustrBuffer.ToCArray(), &w, NULL);

    if (w <= iWidth)
    {
        int iLastLineEnd = 0;

        AddLine(ustrBuffer.SubVector(iLastLineEnd), MessageColour);
    }
    else
    {
        bool bEnd = false;

        int iLastLineEnd = 0;

        int w = 0;
        int wend = 0;

        TTF_SizeUNICODE(MessageFont, ustrBuffer.SubArray(0, 1), &w, NULL);

        int curw = w;

        UnicodeString ustrLine = string("");

        for (int i = 0; i < ustrBuffer.length(); i++)
        {
            // Stop overflow on whole numbers of lines
            if ((i + 1) >= ustrBuffer.length())
            {
                i = ustrBuffer.length();

                break;
            }

            TTF_SizeUNICODE(MessageFont, ustrBuffer.SubArray(i+1, 1), &w, NULL);

            if ((curw + w) >= iWidth)
            {
                AddLine(ustrBuffer.SubVector(iLastLineEnd, (i - iLastLineEnd)), MessageColour);

                iLastLineEnd = i;

                curw = w;
            }
            else
            {
                curw += w;
            }
        }

        if (iLastLineEnd < ustrBuffer.length())
        {
            AddLine(ustrBuffer.SubVector(iLastLineEnd), MessageColour);
        }
    }

    return 0;
}

void Chatbox::AddLine(UnicodeString ustrLine, const SDL_Color& MessageColour)
{
    Lines.push_back(OptimiseAlphaSurface(TTF_RenderUNICODE_Blended(MessageFont, ustrLine.ToCArray(), MessageColour)));

    if (Lines.size() > iMaxLines)
    {
        delete Lines.at(0);
        Lines.erase(Lines.begin());

        Scrollbar.RemoveNotch();
    }

    iTotalHeight += Lines.back()->h;

    // Autoscroll
    if (iTotalHeight > iHeight)
    {
        Scrollbar.setScrollEnabled(true);
        Scrollbar.AddNotch();

        if (bAutoscroll == true)
        {
            Scrollbar.ScrollToBottom();
        }
    }
}

int Chatbox::BlitToFrame(SDL_Surface *surface, Point FramePosition)
{
    if (bVisible == true)
    {
        SDL_Rect dest, clip, lastclip;

        int iCurHeight = 0;
        int iCurLine = Scrollbar.getCurNotch();

        clip.x = (int)Position.x + (int)FramePosition.x;
        clip.y = (int)Position.y + (int)FramePosition.y;
        clip.w = iWidth;
        clip.h = iHeight;

        SDL_GetClipRect(surface, &lastclip);
        SDL_SetClipRect(surface, &clip);

        while (iCurHeight <= iHeight)
        {
            if (iCurLine >= Lines.size())
            {
                iCurHeight = iHeight + 1;

                continue;
            }
            else
            {
                dest.x = (int)Position.x + (int)FramePosition.x;
                dest.y = ((int)Position.y + (int)FramePosition.y) + iCurHeight;

                SDL_BlitSurface(Lines.at(iCurLine), NULL, surface, &dest);

                iCurHeight += Lines.at(iCurLine)->h;

                iCurLine++;
            }
        }

        SDL_SetClipRect(surface, &lastclip);

        Scrollbar.BlitToFrame(surface, FramePosition);
    }
}

int Chatbox::getMaxLines()
{
    return iMaxLines;
}

bool Chatbox::getAutoscroll()
{
    return bAutoscroll;
}

void Chatbox::setAutoscroll(const bool& bNewAutoscroll)
{
    bAutoscroll = bNewAutoscroll;
}
